#include "common.h"

/*** Echo-server ***/

#define NUM_TO_ACTION 3

typedef std::vector<BaseConsumer*> cons_arr_t;

void consume(cons_arr_t& consumers, std::string const& s) {
    for (cons_arr_t::iterator it = consumers.begin(); it != consumers.end(); ++it) {
        if ((*it)->deserialize(s))
            break;
    }
}

void do_action(cons_arr_t& consumers) {
    for (cons_arr_t::iterator it = consumers.begin(); it != consumers.end(); ++it)
        (*it)->action();
}

void init(cons_arr_t& consumers) {
    consumers.push_back(new ConsumerA());
    consumers.push_back(new ConsumerB());
    consumers.push_back(new ConsumerC());
}

void clear(cons_arr_t& consumers) {
    for (cons_arr_t::iterator it = consumers.begin(); it != consumers.end(); ++it)
        delete (*it);
}

int main() {
    int listener;
    struct sockaddr_in addr;
    char buf[BUF_SIZE];

    listener = socket(AF_INET, SOCK_STREAM, 0);
    if (listener < 0) {
        perror("Error in socket creation");
        return errno;
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(MY_PORT);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(listener, (struct sockaddr*) &addr, sizeof(addr)) < 0) {
        perror("Error in binding");
        return errno;
    }

    cons_arr_t consumers;
    init(consumers);

    size_t counter = 0;
    listen(listener, 1);
    while (1) {
        int sockfd = accept(listener, NULL, NULL);
        if (sockfd < 0) {
            perror("Error in accepting listener");
            return errno;
        }
        while (1) {
            int bytes_read = recv(sockfd, buf, BUF_SIZE, 0);
            if (bytes_read <= 0) 
                break;
            consume(consumers, std::string(buf));
            ++counter;
            send(sockfd, buf, bytes_read, 0);

            if (counter == NUM_TO_ACTION) {
                counter = 0;
                do_action(consumers);
            }
        }
        close(sockfd);
    }   
    close(listener);

    clear(consumers);
    return 0;
}
